package com.example.service.impl;

import com.alibaba.fastjson.JSON;
import com.example.entity.Auth;
import com.example.mapper.AuthMapper;
import com.example.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author:tjf
 * @Description:
 */
@CacheConfig(cacheNames = "com.example.service.impl.AuthServiceImpl")
@Service
public class AuthServiceImpl implements AuthService {
    @Autowired
    private AuthMapper authMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Value("${authTree.parentId}")
    private int authTreeParentId;

    /**
     * 根据userId查询对应权限树的业务方法
     * 先查缓存，若缓存没有权限树再到数据库找
     * @param userId
     * @return
     */
    @Override
    public List<Auth> findAuthTreeByUserId(int userId) {
        // 先从数据库中查询，查询的是权限树的json串
        String authTreeListJson = stringRedisTemplate.opsForValue().get(userId + ":authTree");

        if (StringUtils.hasText(authTreeListJson)){// redis缓存中有authTreeList的json串
            // 把List<Auth>的json字符串形式转为List<Auth>
            List<Auth> authTreeList = JSON.parseArray(authTreeListJson, Auth.class);
            return authTreeList;
        }

        // redis缓存中没有authTreeList的json串
        List<Auth> allAuthList = authMapper.findAllAuthByUserId(userId);

        // 把allAuthList转为权限树
        List<Auth> authTree = allAuthListToAuthTree(allAuthList, authTreeParentId);

        // 把List<Auth>转为json字符串后保存到redis缓存中
        stringRedisTemplate.opsForValue().set(userId + ":authTree", JSON.toJSONString(authTree));

        // 返回权限树
        return authTree;
    }

    /**
     * 将所有的auth转为authTree的业务方法
     * @return
     */
    @Cacheable(key = "'allAuthTree:auth'")
    @Override
    public List<Auth> transformAllAuthToAuthTree() {
        // 查询所有的auth
        List<Auth> authList = authMapper.selectAllAuth();

        // 将查询的所有auth转为authTree
        List<Auth> authTreeList = allAuthListToAuthTree(authList, authTreeParentId);

        // 将authTreeList以json字符串的形式添加到redis中
        stringRedisTemplate.opsForValue().set("allAuthTree:auth", JSON.toJSONString(authTreeList));

        // 响应结果
        return authTreeList;
    }

    /**
     * 根据roleId查询所有authId的业务方法
     * @param roleId
     * @return
     */
    @Override
    public List<Integer> queryAuthIdByRoleId(int roleId) {
        // 查询属于roleId的权限
        List<Integer> authIdList = authMapper.selectAuthIdByRoleId(roleId);

        return authIdList;
    }

    /**
     * 将所有的auth转为一棵或多棵权限树的算法
     * @param allAuthList userId对应的所有权限
     * @param parentId 父权限id
     * @return
     */
    private List<Auth> allAuthListToAuthTree(List<Auth> allAuthList, int parentId){
        ArrayList<Auth> authList = new ArrayList<>();

        // 找出parentId与参数parentId相同的auth对象，parentId从0开始
        for (Auth auth : allAuthList) {
            if (auth.getParentId() == parentId){
                authList.add(auth);
            }
        }

        // 找出auth的所有子级auth
        for (Auth auth : authList) {
            List<Auth> childAuthList = allAuthListToAuthTree(allAuthList, auth.getAuthId());
            auth.setChildAuth(childAuthList);
        }

        // 最终返回权限树
        return authList;
    }
}
